#coding=utf-8

import Queue
import threading, time
import cv2
import numpy as np
import  datetime
'''
使用多线程，将4个视频合成到1个画面，实现画中画效果。
生产者消费者：使用队列通信
效果：
CPU100%：去掉sleep代码，CPU很快就飙升到100%
内存100%：去掉queue.qsize() > 10，内存很快飙升到100%，生产太快，每次放4帧，占用内存大
更慢：2分钟的视频，单线程处理5分钟，多线程处理7.8分钟，增加了sleep和线程切换。

'''
lock = threading.Lock()
queue = Queue.Queue() #maxsize=1
is_over = False

def Producer():
   read_video()


def Consumer():
    merge_video()


def read_video():
    global  is_over,lock,queue
    videoLeftUp = cv2.VideoCapture(r'D:\data\test\1.mp4')
    videoLeftDown = cv2.VideoCapture(r'D:\data\test\2.mp4')
    videoRightUp = cv2.VideoCapture(r'D:\data\test\3.mp4')
    videoRightDown = cv2.VideoCapture(r'D:\data\test\4.mp4')

    while True:
        if  queue.qsize() > 10:
            time.sleep(0.1)
            continue

        start_time = datetime.datetime.now()

        successLeftUp, frameLeftUp = videoLeftUp.read()
        successLeftDown, frameLeftDown = videoLeftDown.read()
        successRightUp, frameRightUp = videoRightUp.read()
        successRightDown, frameRightDown = videoRightDown.read()

        if successLeftUp and successLeftDown and successRightUp and successRightDown:

            lock.acquire()
            try:
                queue.put((frameLeftUp, frameLeftDown, frameRightUp, frameRightDown))
            finally:
                lock.release()

            end_time = datetime.datetime.now()
            print "read_seconds:  %s" % (end_time - start_time).total_seconds()
        else:
            is_over = True
            break
        time.sleep(0.1)
    videoLeftUp.release()
    videoLeftDown.release()
    videoRightUp.release()
    videoRightDown.release()




def merge_video():
    global is_over, lock, queue
    videoLeftUp = cv2.VideoCapture(r'D:\data\test\1.mp4')

    fps = videoLeftUp.get(cv2.CAP_PROP_FPS)
    width = (int(videoLeftUp.get(cv2.CAP_PROP_FRAME_WIDTH)))
    height = (int(videoLeftUp.get(cv2.CAP_PROP_FRAME_HEIGHT)))
    videoWriter = cv2.VideoWriter(r'D:\data\test\merge.mp4', cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), fps,(width, height))

    while True:
        if not queue.empty():
            start_time = datetime.datetime.now()

            lock.acquire()
            try:
                t = queue.get()
            finally:
                lock.release()

            frameLeftUp = t[0]
            frameLeftDown = t[1]
            frameRightUp = t[2]
            frameRightDown = t[3]

            frameLeftUp = cv2.resize(frameLeftUp, (int(width / 2), int(height / 2)), interpolation=cv2.INTER_CUBIC)
            frameLeftDown = cv2.resize(frameLeftDown, (int(width / 2), int(height / 2)), interpolation=cv2.INTER_CUBIC)
            frameRightUp = cv2.resize(frameRightUp, (int(width / 2), int(height / 2)), interpolation=cv2.INTER_CUBIC)
            frameRightDown = cv2.resize(frameRightDown, (int(width / 2), int(height / 2)), interpolation=cv2.INTER_CUBIC)

            frameUp = np.hstack((frameLeftUp, frameRightUp))
            frameDown = np.hstack((frameLeftDown, frameRightDown))
            frame = np.vstack((frameUp, frameDown))
            videoWriter.write(frame)
            end_time = datetime.datetime.now()
            print "write_seconds:  %s" % (end_time - start_time).total_seconds()

        else:
            if is_over:
                break
            else:
                time.sleep(0.1)
        time.sleep(0.1)

    videoWriter.release()


if __name__ == "__main__":
    p = threading.Thread(target=Producer)
    c = threading.Thread(target=Consumer)

    start_time = datetime.datetime.now()
    p.start()
    c.start()

    p.join()
    c.join()
    end_time = datetime.datetime.now()
    print  "total:%s" %   ( end_time - start_time ).total_seconds()
